home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / spooldb.com / SPOOL.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-05-25  |  26.8 KB  |  610 lines

  1. {==============================================================================
  2.  Name: Spool.pas
  3.  
  4.  Description: This unit allows a program to spool text files and print them
  5.               while the program does other process.  It provides several
  6.               functions to add and delete spool request, and to halt the
  7.               spooler.
  8.               The DOS command PRINT must be executed before the program is
  9.               run.  You may elect to place the print command in a batch file
  10.               or leave it up to the user.
  11.               The basic flow of logic is as follows.  You pass the spooler a
  12.               file name to send to the printer.  It ques it and places the
  13.               name on a stack.  While your program processes other tasks the
  14.               file is printed.  Other files can be sent before the first
  15.               file is finished.  When your program exits, the spooler unit
  16.               will check to see if there are any print requests pending.  If
  17.               there is, the spooler unit will ask the user if he wants to
  18.               halt the spooler and exit.  If the halt option is chosen the
  19.               spooler is then halted, and all spool files deleted.  If he
  20.               chooses to wait, the program will sit and wait until all files
  21.               are processed, upon completion the unit will beep three times.
  22.               The user may also choose to exit and continue printing.  If
  23.               this option is chosen, the program will terminate, but the
  24.               print requests will continue to be printed.  The spool files
  25.               will not be deleted, and should be deleted upon starting the
  26.               your program, this is up to the main program.  All print
  27.               requests can be handled by the standard DOS command "PRINT".
  28.               It is up to the main program to supply the names for the spooler.
  29.               You can use any names you wish.  The most conventional would be a
  30.               base with a numeric extension.  If you elect, the spooler can
  31.               generate a spool name.  It will return the next logical name.
  32.               The base will be SPOOL and will contain a three digit numeric
  33.               extension starting with 000.  It is not wise to delete or modify
  34.               the spool files while they are qued.  If you wish you may delete
  35.               them from the spooler using the standard Cancel_Files command.
  36.               Spool files can reside anywhere.
  37.               One last note, the variable SpoolExitProc is a procedure
  38.               variable.  You can set this variable to a procedure you want
  39.               executed before your program terminates, that will give you a
  40.               chance to do something about the spooler before your program
  41.               exits. There is a default routine that is activated if you choose
  42.               not to write your own.  It asks whether you want to halt the
  43.               spooler, wait for the spooler to finish, or exit and leave the
  44.               spooler printing.  To use your own you will need to write a
  45.               procedure, there should be no parameters.  Next, somewhere near
  46.               the beginning of your program place the following statement:
  47.  
  48.               SpoolExitProc:=YourProcedure;
  49.  
  50.               Now, upon exiting your program, "YourProcedure" will be called.
  51.  
  52.               The two procedures you'll use most is Get_Spool_Name and Submit.
  53.               The first will supply a spool name for you and the second will
  54.               submit the last spool name generated.  This gives a quick way
  55.               of using the spooler.  There are other options that give you
  56.               more control.
  57.  
  58.  Author: David Bradley
  59.  
  60.  VERSION: 1.1
  61.  
  62.  This software is donated to the public domain.  All I ask is that you leave
  63.  my name where it is, I need some credit.  I hope you find this software
  64.  usefull.
  65. =============================================================================}
  66.  
  67. unit Spool;
  68.  
  69. interface
  70.  
  71. uses
  72.   Crt,
  73.   Dos;
  74.  
  75. var
  76.   Spool_Extension_Number:integer;             { Contains the current extension number, for automatic name generation }
  77.  
  78. { Hook for main program to replace exit logic of spooler 5.0 specific }
  79. {$IFNDEF VER40}
  80.   SpoolExitProc:procedure;
  81. {$ENDIF }
  82.  
  83. { This proceure automatically submits the last spool file name generated by the
  84.   Get_Spool_Name function. }
  85.  
  86. procedure Submit;
  87.  
  88.  
  89. { Submit a file to the spooler }
  90.  
  91. function Submit_File(Name:string):boolean;
  92.  
  93.  
  94. { Submit files to the spooler, wild cards allowed }
  95.  
  96. function Submit_Files(Name:string):boolean;
  97.  
  98.  
  99. { Cancel a spooled file, wild cards allowed }
  100.  
  101. function Cancel_File(Name:string):boolean;
  102.  
  103.  
  104. { Terminate the spooler - stops printing and cancels all pending jobs }
  105.  
  106. procedure Terminate_Spooler;
  107.  
  108.  
  109. { Get the next spooler entry, each sucessive call returns the next file name
  110.   , if null (''), you are at the end of the list.  Another call will return
  111.   the first name again.  This function pauses the spooler, you'll need to use
  112.   Resume_Spooler after your have retrieved all the names you want. }
  113.  
  114. function Get_Spooler_Entry:string;
  115.  
  116.  
  117. { Pause the spooler, stops printing, use Resume_Spooler to continue printing }
  118.  
  119. procedure Pause_Spooler;
  120.  
  121.  
  122. { Resume the spooler, after it has been paused }
  123.  
  124. procedure Resume_Spooler;
  125.  
  126.  
  127. { Check to see if spooler (PRINT) has been installed }
  128.  
  129. function Spooler_Installed:boolean;
  130.  
  131.  
  132. { Get the next spool name - this function allows you to allocate file names
  133.   to reports you want to spool.  The names begin with SPOOL and have a
  134.   numeric extension.  You can pass any name to the spooler system, this is
  135.   just a handy way to keep the names straight.}
  136.  
  137. function Get_Spool_Name:string;
  138.  
  139.  
  140. { Check to see if the spooler is empty }
  141.  
  142. function Spooler_Empty:boolean;
  143.  
  144. {$IFDEF VER40}
  145. procedure SpoolExit;
  146. {$ENDIF }
  147.  
  148. implementation
  149.  
  150. type
  151.   Packet_Type=record                          { Layout of Packet data for PRINT }
  152.                 Level:byte;                   { Level ??? }
  153.                 ASCIIZ:pointer;               { Pointer to file name }
  154.               end;
  155.  
  156.   Spool_Name_Type=record                      { Structure for spool name stack }
  157.                     SName:string[64];         { Name of spool file }
  158.                     Next:pointer;             { Address of next entry / Nil if last }
  159.                   end;
  160. var
  161.   Spooler_Halted:boolean;                     { Flag to indicate if spooler has been halted }
  162.   Spooler_List:pointer;                       { Pointer to interal list of file qued file names }
  163.   Spool_Name_List:pointer;                    { Pointer to begging of spool file name stack }
  164.   OldExitProc:pointer;                        { Holds old exit pointer }
  165.   Last_Spool_Name:string;                     { Holds last spool name generated }
  166.  
  167. {=============================================================================}
  168. {                             BEEPS SPEEKER (For internal use)                }
  169. {=============================================================================}
  170. procedure Beep;
  171. begin
  172.   Sound(1000);
  173.   Delay(500);
  174.   NoSound;
  175. end;
  176.  
  177. {=============================================================================}
  178. { Add a name to the spool name stack (For internal use )                      }
  179. {=============================================================================}
  180. function Add_Spool_Name(Name:string):boolean;
  181. var
  182.   Spool_Name:^Spool_Name_Type;                      { Pointer to spool info }
  183.   Last_Spool_Name:^Spool_Name_Type;                 { Another pointer }
  184.  
  185. begin
  186.   if MemAvail<SizeOf(Spool_Name_Type)+4 then        { Check available memory }
  187.   begin
  188.     Add_Spool_Name:=false;                          { No memory, return false }
  189.     exit;                                           { and exit function }
  190.   end;
  191.   New(Spool_Name);                                  { Allocate memory for new spool file name }
  192.   Spool_Name^.Next:=Nil;                            { Clear next pointer of new element }
  193.   Spool_Name^.SName:=Name;                          { Place name of spool file into element }
  194.   if Spool_Name_List=Nil then                       { If spool name list is emtpy }
  195.     Spool_Name_List:=Spool_Name                     { Set the list pointer to point to the new element }
  196.   else                                              { Else if there are elements in the list }
  197.   begin
  198.     Last_Spool_Name:=Spool_Name_List;               { Find the last element in the list }
  199.     while Last_Spool_Name^.Next<>Nil do Last_Spool_Name:=Last_Spool_Name^.Next;
  200.     Last_Spool_Name^.Next:=Spool_Name;              { Point last element to new element }
  201.   end;
  202.   Add_Spool_Name:=true;                             { Everything OK return now }
  203. end;
  204.  
  205. {=============================================================================}
  206. { Delete a spool name from the spool name stack                               }
  207. {=============================================================================}
  208. procedure Delete_Spool_Name(Name:string);
  209. var
  210.   Previous:pointer;                                 { Holds address of previous element }
  211.   Next:pointer;                                     { Holds address of next element }
  212.   Spool_Name:^Spool_Name_Type;                      { Pointer to spool list element }
  213.  
  214. begin
  215.   Spool_Name:=Spool_Name_List;                      { Position to first element in the list }
  216.   Previous:=Nil;                                    { Initialize Previous pointer }
  217.   while Spool_Name<>Nil do                          { While not at the end of the list }
  218.   begin
  219.     if Spool_Name^.SName=Name then                  { If Name is the same as element's name }
  220.     begin
  221.       Next:=Spool_Name^.Next;                       { Set Next pointer to the targetted element's next pointer }
  222.       Dispose(Spool_Name);                          { Free up memory used be targetted element }
  223.       if Previous=Nil then                          { If this is the first element }
  224.         Spool_Name_List:=Next                       { Then set spool name list pointer to next element }
  225.       else                                          { else if this is not the first element }
  226.       begin
  227.         Spool_Name:=Previous;                       { Got back to the previous element looked at }
  228.         Spool_Name^.Next:=Next;                     { Set the next pointer of the previous element to }
  229.       end;                                          { the next pointer saved earlier }
  230.       Exit;                                         { Exit procedure }
  231.     end
  232.     else                                            { Else if this is not the name we want }
  233.     begin
  234.       Previous:=Spool_Name;                         { Set previous pointer to current element }
  235.       Spool_Name:=Spool_Name^.Next;                 { Position to next element }
  236.     end;
  237.   end;                                              { End of while loop, exits if end of list reached }
  238. end;
  239.  
  240. {=============================================================================}
  241. { This submits the file name that was last generated by the Get_Spool_Name    }
  242. { function                                                                    }
  243. {=============================================================================}
  244. procedure Submit;
  245. begin
  246.   if not Spooler_Installed then exit;               { Check to see if PRINT is resident }
  247.   if Submit_File(Last_Spool_Name) then;             { Submit last spool name generated to spooler }
  248. end;
  249.  
  250. {=============================================================================}
  251. { Submits a name to the print spooler, no wildcard characters / this routine  }
  252. { is used mainly by Submit_Files.  This should only be used if you are going  }
  253. { to submit one file at a time, this will speed up the process.               }
  254. {=============================================================================}
  255. function Submit_File(Name:string):boolean;
  256. var
  257.   Regs:registers;                                   { Register variables for DOS function calls }
  258.   SubmitPacket:Packet_Type;                         { Packet variable for file submissions to spooler }
  259.  
  260.   { This function checks for the existance of a file }
  261.   function Exist(N:string):boolean;
  262.   var
  263.     F:File;                                         { Dummy file variable }
  264.     OK:boolean;
  265.  
  266.   begin
  267.     assign(F,N);                                    { Assign file name to file variable }
  268.     reset(F);                                       { Try to open file }
  269.     OK:=IOResult=0;                                 { Check for an I/O error }
  270.     if OK then close(F);                            { Close the file if it was opened }
  271.   end;
  272.  
  273. begin
  274.   if not Exist(Name) or not Spooler_Installed then  { If file doesn't exist }
  275.   begin
  276.     Submit_File:=false;                             { Return a value of false }
  277.     exit;                                           { Exit this function }
  278.   end;
  279.   with SubmitPacket do
  280.   begin
  281.     Level:=0;                                       { Set level to 0 }
  282.     ASCIIZ:=Addr(Name);                             { Pass address of Name to packet variable }
  283.     Name[length(Name)+1]:=#0;                       { Place a ASCII 0 at end of string }
  284.     inc(longint(ASCIIZ));                           { Increment the string pointer by 1 }
  285.   end;                                              { This passes up the length byte }
  286.   Regs.AX:=$0101;                                   { Submit file function }
  287.   Regs.DS:=Seg(SubmitPacket);                       { Pass segment address of packet variable }
  288.   Regs.DX:=Ofs(SubmitPacket);                       { Pass offset of address of packet variable }
  289.   Intr($2F,Regs);                                   { Call interrupt }
  290.   if (FCarry and Regs.Flags)=0 then                 { If carry wasn't set }
  291.   begin
  292.     Submit_File:=Add_Spool_Name(Name);              { Add file name to list and return result }
  293.     exit;                                           { exit function }
  294.   end
  295.   else                                              { Else if the carry flag is set }
  296.   begin
  297.     Submit_File:=false;                             { Return a value of false }
  298.     exit;                                           { exit function }
  299.   end;
  300. end;
  301.  
  302. {=============================================================================}
  303. { Submits a file or files to the print que, standard DOS wildcard characters  }
  304. { are allowed.                                                                }
  305. {=============================================================================}
  306. function Submit_Files(Name:string):boolean;
  307. var
  308.   SRec:SearchRec;                                   { Search variable for FindNext procedure }
  309.   LastSlash,                                        { Position of last slash in file name }
  310.   Count:integer;                                    { Counter for "for" loop }
  311.   Path:string[64];                                  { Holds path of file }
  312.  
  313. begin
  314.   if not Spooler_Installed then                     { if PRINT is not resident, exit }
  315.   begin
  316.     Submit_Files:=false;
  317.     exit;
  318.   end;
  319.   LastSlash:=0;                                     { Set LastSlash to 0 }
  320.   Path:='';                                         { Set Path to Null }
  321.   for Count:=1 to length(Name) do                   { Process each character of string Name }
  322.     if Name[Count]='\' then                         { If the character of Name is a backslash }
  323.       LastSlash:=Count;                             { then set LastSlash to current position in string }
  324.   if LastSlash>0 then Path:=copy(Path,1,LastSlash); { Copy the path part of the file name to Path }
  325.   FindFirst(Name,0,SRec);                           { Find the first matching name }
  326.   while DosError=0 do                               { If found }
  327.   begin
  328.     if not Submit_File(Path+SRec.Name) then         { Submit the file to the spooler }
  329.     begin
  330.       Terminate_Spooler;                            { If there was an error, terminate the spooler }
  331.       Submit_Files:=false;                          { Return a value of false }
  332.       exit;                                         { Exit the function }
  333.     end;
  334.     FindNext(SRec);                                 { Get next matching file name }
  335.   end;
  336.   if DosError<>18 then                              { If the DOS Error was anything but file not found }
  337.   begin
  338.     Submit_Files:=false;                            { Return a value of false }
  339.     exit;                                           { and exit function }
  340.   end
  341.   else                                              { Else if file not found }
  342.   begin
  343.     Submit_Files:=true;                             { return a value of true }
  344.     exit;                                           { and exit function }
  345.   end;
  346. end;
  347.  
  348. {=============================================================================}
  349. { Cancels a file on the que and deletes the name for the spool name stack     }
  350. {=============================================================================}
  351. function Cancel_File(Name:string):boolean;
  352. var
  353.   Regs:registers;                                   { Register variable for interrupts }
  354.  
  355. begin
  356.   if not Spooler_Installed then                     { if PRINT is not resident, exit }
  357.   begin
  358.     Cancel_File:=false;
  359.     exit;
  360.   end;
  361.   Regs.AX:=$0102;                                   { Load cancel function call number }
  362.   Regs.DS:=Seg(Name);                               { Load segment of address of file name variable }
  363.   Regs.DX:=Ofs(Name);                               { Load offset of address of file name variable }
  364.   Intr($2F,Regs);                                   { Call multiplex interrupt }
  365.   if (FCarry and Regs.Flags)=0 then                 { If carry flag wasn't set (OK)}
  366.     Delete_Spool_Name(Name);                        { Delete name from list of spool names }
  367.   Cancel_File:=(FCarry and Regs.Flags)=0;           { Return a value of true if carry flag not set }
  368. end;
  369.  
  370. {=============================================================================}
  371. { This terminates the spooler, all spool files are left intact.               }
  372. {=============================================================================}
  373. procedure Terminate_Spooler;
  374. var
  375.   Regs:registers;                                   { Register variable for interrupt }
  376.  
  377. begin
  378.   if not Spooler_Installed then exit;               { if PRINT is not resident, exit }
  379.   Regs.AX:=$0103;                                   { Load terminate function call number }
  380.   Intr($2F,Regs);                                   { Call multiplex interrupt }
  381. end;
  382.  
  383. {=============================================================================}
  384. { Gets the next spooler name, if blank there are no entries.  Also it pauses  }
  385. { the spooler.  As soon as you have gotten all the names you need, use        }
  386. { Resume_Spooler to continue printing.                                        }
  387. {=============================================================================}
  388. function Get_Spooler_Entry:string;
  389. type
  390.   Entry=array[1..64] of byte;                       { variable type declaration for spool name entry }
  391.  
  392. var
  393.   Regs:registers;                                   { Register variable }
  394.   Hold:^Entry;                                      { Variable to point to spool name entry }
  395.   S:string;                                         { String variable }
  396.   Position:integer;                                 { Holds position of end of string }
  397.  
  398. begin
  399.   if not Spooler_Installed then                     { if PRINT is not resident, exit }
  400.   begin
  401.     Get_Spooler_Entry:='';
  402.     exit;
  403.   end;
  404.   if not Spooler_Halted then                        { if spooler is not halted }
  405.   begin
  406.     Regs.AX:=$0104;                                 { then halt the spooler }
  407.     Intr($2F,Regs);
  408.     Spooler_List:=Ptr(Regs.DS,Regs.SI);             { Set spooler list to start of list }
  409.     Spooler_Halted:=true;
  410.   end;
  411.   Hold:=Spooler_List;                               { Point hold to list of spool entries }
  412.   if Hold^[1]=0 then                                { If entry is null }
  413.   begin
  414.     Resume_Spooler;                                 { Resume the spooler }
  415.     Get_Spooler_Entry:='';                          { and return null }
  416.     exit;
  417.   end;
  418.   Position:=1;                                      { Set position variable }
  419.   while (Hold^[Position]<>32) and (Hold^[Position]<>0) do  { Repeat until space or null character }
  420.   begin
  421.     S[Position]:=char(Hold^[Position]);             { Move character to string }
  422.     inc(Position);                                  { Next character }
  423.   end;
  424.   S[0]:=chr(Position-1);                            { Set length of string }
  425.   inc(longint(Spooler_List),64);                    { Move spooler list variable to next entry }
  426.   Get_Spooler_Entry:=S;                             { Return name }
  427. end;
  428.  
  429. {=============================================================================}
  430. { Temporarily pauses the spooler.  Use Resume_Spooler to continue.            }
  431. {=============================================================================}
  432. procedure Pause_Spooler;
  433. var
  434.   Regs:registers;
  435.  
  436. begin
  437.   if not Spooler_Installed then exit;               { if PRINT is not resident, exit }
  438.   Regs.AX:=$0104;
  439.   Intr($2F,Regs);
  440.   Spooler_List:=Ptr(Regs.DS,Regs.SI);
  441.   Spooler_Halted:=true;
  442. end;
  443.  
  444. {=============================================================================}
  445. { Resumes spooling due to a Pause_Spooler or a Get_Spool_Entry.               }
  446. {=============================================================================}
  447. procedure Resume_Spooler;
  448. var
  449.   Regs:registers;
  450.  
  451. begin
  452.   if not Spooler_Installed then exit;               { if PRINT is not resident, exit }
  453.   Regs.AX:=$0105;
  454.   Intr($2F,Regs);
  455.   Spooler_List:=Nil;
  456.   Spooler_Halted:=false;
  457. end;
  458.  
  459. {=============================================================================}
  460. { Tells you if a spooler is installed.                                        }
  461. {=============================================================================}
  462. function Spooler_Installed:boolean;
  463. var
  464.   Regs:registers;
  465.  
  466. begin
  467.   Regs.AX:=$0100;
  468.   Intr($2F,Regs);
  469.   Spooler_Installed:=Regs.Al=$FF;
  470. end;
  471.  
  472. {=============================================================================}
  473. { Erases a file, internal procedure only                                      }
  474. {=============================================================================}
  475. procedure EraseF(Name:string);
  476. var
  477.   F:File;
  478.  
  479. begin
  480.   assign(F,Name);
  481.   erase(F);
  482. end;
  483.  
  484. {=============================================================================}
  485. { Exit logic to check for spooling activity before a program ends.  This is a }
  486. { simplist routine to afford the user some options before the program ends.   }
  487. { The programmer may elect to check for spooler activity via the main program }
  488. { and afford a more gracefull exit logic.  You can check for spooler activity }
  489. { by using the Get_Spool_Entry, if a name is returned then the spooler is     }
  490. { still printing.  Remember to use resume if you wish to continue spooling    }
  491. {=============================================================================}
  492. {$F+}
  493. procedure SpoolExit;
  494. var
  495.   Name:string;
  496.   Spool_Name:^Spool_Name_Type;
  497.   Answer:char;
  498.   Count:integer;
  499.   NextName:pointer;
  500.  
  501. begin
  502.   ExitProc:=OldExitProc;
  503.   if Spooler_Installed then
  504.   begin
  505.     Name:=Get_Spooler_Entry;
  506.     Resume_Spooler;
  507.     if Name<>'' then
  508.     begin
  509.       TextColor(7);
  510.       TextBackground(0);
  511.       ClrScr;
  512.       writeln('Spooler is active, select on of the following:'+chr(13));
  513.       writeln('(H)alt spooler,');
  514.       writeln('(W)ait until finished,');
  515.       writeln('(E)xit and leave spooler files to be processed');
  516.       repeat
  517.         read(Answer);
  518.         Answer:=UpCase(Answer);
  519.       until Answer in ['E','H','W'];
  520.       if Answer='E' then exit;
  521.       if Answer='W' then
  522.       begin
  523.         repeat
  524.           ClrScr;
  525.           gotoxy(20,12);
  526.           write('Waiting for spooler to complete printing');
  527.           Name:=Get_Spooler_Entry;
  528.           Resume_Spooler;
  529.           for Count:=1 to 30000 do;
  530.         until Name='';
  531.         Beep;
  532.         Beep;
  533.         Beep;
  534.       end;
  535.       if Answer='H' then
  536.         Terminate_Spooler;
  537.     end;
  538.   end;
  539.   Spool_Name:=Spool_Name_List;
  540.   while Spool_Name<>Nil do
  541.   begin
  542.     EraseF(Spool_Name^.SName);
  543.     Spool_Name:=Spool_Name^.Next;
  544.   end;
  545.   Spool_Name:=Spool_Name_List;
  546.   while Spool_Name<>Nil do
  547.   begin
  548.     NextName:=Spool_Name^.Next;
  549.     Dispose(Spool_Name);
  550.     Spool_Name:=NextName;
  551.   end;
  552. end;
  553. {$F-}
  554.  
  555. {=============================================================================}
  556. { Returns then next logical spool name (SPOOL.000, SPOOL.001, SPOOL.002...)   }
  557. {=============================================================================}
  558. function Get_Spool_Name:string;
  559. var
  560.   Extension:string[4];
  561.   Count:integer;
  562.  
  563. begin
  564.   if not Spooler_Installed then                     { if PRINT is not resident, exit }
  565.   begin
  566.     Get_Spool_Name:='';
  567.     exit;
  568.   end;
  569.   str(Spool_Extension_Number:3,Extension);          { Convert spool number to string }
  570.   for Count:=1 to length(Extension) do              { Change blanks in extension to zeros }
  571.     if Extension[Count]=' ' then Extension[Count]:='0';
  572.   inc(Spool_Extension_Number);                      { Increment extension number }
  573.   Spool_Extension_Number:=Spool_Extension_Number mod 1000;  { Extension must be between 0 and 1000 }
  574.   Last_Spool_Name:='SPOOL.'+Extension;              { Build spool name with extension }
  575.   Get_Spool_Name:=Last_Spool_Name;                  { return name }
  576. end;
  577.  
  578. {=============================================================================}
  579. { This tests to see if the spooler is empty                                   }
  580. {=============================================================================}
  581. function Spooler_Empty:boolean;
  582. var
  583.   Name:string;
  584.  
  585. begin
  586.   if not Spooler_Installed then                     { if PRINT is not resident, exit }
  587.   begin
  588.     Spooler_Empty:=true;
  589.     exit;
  590.   end;
  591.   Name:=Get_Spooler_Entry;
  592.   Resume_Spooler;
  593.   Spooler_Empty:=Name='';
  594. end;
  595.  
  596. {=============================================================================}
  597. { Initialization logic for Spool unit.                                        }
  598. {=============================================================================}
  599. begin
  600.   { The next three lines will need to be modified for version 4.0 }
  601. {$IFNDEF VER40}
  602.   SpoolExitProc:=SpoolExit;                         { Set default exit procedure, 5.0 specific }
  603.   OldExitProc:=ExitProc;                            { Save old exit procedure address }
  604.   ExitProc:=@SpoolExitProc;                         { Set new exit procedure to SpoolExitProc }
  605. {$ENDIF }
  606.   Spooler_Halted:=false;                            { Initialize variables }
  607.   Spooler_List:=Nil;
  608.   Spool_Name_List:=Nil;
  609.   Spool_Extension_Number:=0;
  610. end.